/*
 * tdeapporo.h
 *
 *  Created on: 28/04/2010
 *      Author: javier
 */
#ifndef TDEAPPORO_CPP_
#define TDEAPPORO_CPP_

#include "tporo.h"
#include "tvectorporo.h"
#include "tabbporo.h"

using namespace std;

/** \file tdeapporo.h
 *  \brief Implementacion de la clase TDeapPoro.
 *
 * Fichero que contiene la definicion y los métodos de la clase TDeapPoro.
 */


enum THeap {Hmin,Hmax};

/** \brief Clase TDeapPoro.
 *
 * Clase que representa la estructura de un montículo doble.
 */
class TDeapPoro
{
	friend ostream & operator<<( ostream &, const TDeapPoro & );

	public:

		/** \brief Constructor de la clase.
		 *
		 * Constructor de la clase por defecto, inicializamos el vector interno y la posicion a la primera donde queremos insertar, la segunda.
		 */
		TDeapPoro();

		/** \brief Constructor de copia.
		 *
		 * Constructor de copia de la clase.
		 * \param deap Deap desde el que copiamos.
		 */
		TDeapPoro( const TDeapPoro & );

		 /** Destructor.
		 *
		 * Destructor de la clase, elimina el vector y pone el entero "posicion" a 0.
		 */
		~TDeapPoro();

		 /** \brief Sobrecarga del operador asignación.
		 *
		 * Si el deap que llama a el metodo tenia contenido es borrado y asignado los valores del argumento.
		 * Si no asigna simplemente.
		 *
		 * \param deap Deap a partir del cual asignamos.
		 * \return TDeapPoro& es devuelto con la correspondiente asignación efectuada.
		 */
		TDeapPoro & operator=( const TDeapPoro &);

		/** \brief Sobrecarga del operador igualdad.
		 *
		 * Comparamos los vectores internos que conforman los Deap, en caso de ser iguales estos, lo seran sus vectores.
		 *
		 * \param deap Deap con el que comparamos.
		 * \return Devuelve un bool, que indica si es igual o distinto.
		 */
		bool operator==( const TDeapPoro &);

        /** \brief Metodo EsVacio().
         *
         * Devuelve true si el Deap esta vacio y false si no lo está.
         * La condicion de que este vacio es que no tenga ningun Poro insertado.
         *
         * \return  Devuelve un bool para indicar su estado.
         */
		bool EsVacio() const;

		/** \brief Operador Insertar.
		 *
		 * Este operador se encarga de la inserción ordenada en Deap. Efectua el procedimiento teorico de insercion en Deap, primero busca si el poro estaba ya insetado.
		 * Luego comprueba las condiciones de tamaño del Deap, simetrias y efectua el proceso de ascender el Poro si es necesario, manteniendo el orden.
		 *
		 *
		 * \param p Un TPoro, el que vamos a insertar.
		 * \return Devuelve un bool, que indica si se ha insertado o no se ha insertado.
		 */
		bool Insertar( const TPoro &);

		/** \brief Operador BorrarMax().
		 *
		 *	BorraMax borra el máximo del Heapmaximo del Deap. En su proceso efectúa los pasos teóricos del borrado del deap
		 *	para mantener el orden en este.
		 *
		 * \return Devuelve un bool, que indica si se ha borrado o no se ha borrado.
		 */
		bool BorrarMax();

		/** \brief Operador BorrarMin().
		 *
		 *	BorraMin borra el minimo del Heapminimo del Deap. En su proceso efectúa los pasos teóricos del borrado del deap
		 *	para mantener el orden en este.
		 *
		 * \return Devuelve un bool, que indica si se ha borrado o no se ha borrado.
		 */
		bool BorrarMin();

		/** \brief Operador Max().
		 *
		 *	Este metodo se encarga de devolvernos el valor del maximo del Deap.
		 *
		 * \return Devuelve un TPoro con el valor del maximo.
		 */
		TPoro Max() const;

		/** \brief Operador Min().
		 *
		 *	Este metodo se encarga de devolvernos el valor del minimo del Deap.
		 *
		 * \return Devuelve un TPoro con el valor del minimo.
		 */
		TPoro Min() const;

		/** \brief Operador Altura().
		 *
		 *	Calcula la altura del Deap y nos la devuelve en forma de entero.
		 *
		 * \return Devuelve un int con el valor de la altura.
		 */
		int Altura() const;

		/** \brief Operador Nodos().
		 *
		 *	Calcula el numero de nodos en el Deap.
		 *
		 * \return Devuelve un int con el numero de nodos.
		 */
		int Nodos() const;

		/** \brief Operador Inorden.
		 *
		 * Inorden nos devuelve el recorrido Inorden del deap.
		 *
		 * \return Devuelve un TVectorPoro con el contenido del recorrido Inorden.
		 */
		TVectorPoro Inorden() const;

		/** \brief Operador Preorden.
		 *
		 * Preorden nos devuelve el recorrido Preorden del deap binario.
		 *
		 * \return Devuelve un TVectorPoro con el contenido del recorrido.
		 */
		TVectorPoro Preorden() const;

		/** \brief Operador Postorden.
		 *
		 * Postorden nos devuelve el recorrido Postorden del deap binario.
		 *
		 * \return Devuelve un TVectorPoro con el contenido del recorrido.
		 */
		TVectorPoro Postorden() const;

		/** \brief Operador Niveles
		 *
		 * Niveles nos devuelve el recorrido del deap por niveles. Es el formato con el que trabajamos internamente en el vector.
		 *
		 *
		 * \return Devuelve un TVectorPoro con el contenido del recorrido.
		 */
		TVectorPoro Niveles() const;

	private:

		// Auxiliar para insertar, nos dira si hay ya un poro del mismo volumen en el vector
		bool Buscaporo( const TPoro &);

		/** \brief Metodo IndentificaHeap.
		 *
		 * Este método auxiliar para toda la clase se encarga de: recibiendo una posicion identificar en que Heap del deap se encuentra esta.
		 *
		 * \param p Posicion de la cual queremos obtener en que heap se encuentra.
		 * \return Devuelve un THeap, tipo enumerado para indicar el heap en el que esta.
		 */
		THeap IdentificaHeap( const int ) const;

		/** \brief Método SimetricoMaximo.
		 *
		 * Obtiene la posición del nodo simétrico en el heap minimo de uno máximo.
		 *
		 * \param i Entero que representa la posición del nodo en el máximo del cual calcularemos su simetrico.
		 * \return Devuelve un entero con la posicion del nodo en el heap minimo.
		 */
		int SimetricoMaximo( const int ) const;

		/** \brief Método SimetricoMinimo.
		 *
		 * Obtiene la posición del nodo simétrico en el heap maximo de un nodo minimo.
		 *
		 * \param j Entero que representa la posición del nodo en el minimo del cual calcularemos su simetrico.
		 * \return Devuelve un entero con la posicion del nodo en el heap maximo.
		 */
		int SimetricoMinimo( const int ) const;

		/** \brief Intercambiar().
		 *
		 * Funcion auxiliar para intercambiar valores en el vector interno del deap.
		 *
		 *	\param i Una posicion para intercambiar con la otra.
		 *	\param j La otra posicion a intercambiar del vector.
		 * \return Void no devuelve nada.
		 */
		void Intercambiar( int i, int );

		/** \brief AscensionMin().
		 *
		 * Funcion auxiliar para realizar la ascension de nodos en el deap, en el heap minimo.
		 *
		 * \param i Entero que indica la posicion del elemento a elevar.
		 * \return Void no devuelve nada.
		 */
		void AscensionMin( int );

		/** \brief AscensionMax().
		 *
		 * Funcion auxiliar para realizar la ascension de nodos en el deap, en el heap maximo.
		 *
		 * \param j Entero que indica la posicion del elemento a elevar.
		 * \return Void no devuelve nada.
		 */
		void AscensionMax( int );

		/** \brief InordenAux.
		 *
		 * Funcion auxiliar de del metodo Inorden().
		 * Mediante un proceso recursivo recorremos el vector del deap, almacenando el nuevo orden en otro vector auxiliar.
		 *
		 * \param vin Vector auxiliar donde guardamos el recorrido.
		 * \param i posicion a examinar para el guardado.
		 * \param auxposicion Indica el lugar del vector auxiliar para guardar en el.
		 * \return TVectorPoro con el contenido del recorrido.
		 */
		TVectorPoro InordenAux( TVectorPoro &, int , int & ) const;

		/** \brief PreordenAux.
		 *
		 * Funcion auxiliar de del metodo Preorden().
		 * Mediante un proceso recursivo recorremos el vector del deap, almacenando el nuevo orden en otro vector auxiliar.
		 *
		 * \param vin Vector auxiliar donde guardamos el recorrido.
		 * \param i posicion a examinar para el guardado.
		 * \param auxposicion Indica el lugar del vector auxiliar para guardar en el.
		 * \return TVectorPoro con el contenido del recorrido.
		 */
		TVectorPoro PreordenAux( TVectorPoro &, int , int & ) const;

		/** \brief PostordenAux.
		 *
		 * Funcion auxiliar de del metodo Postorden().
		 * Mediante un proceso recursivo recorremos el vector del deap, almacenando el nuevo orden en otro vector auxiliar.
		 *
		 * \param vin Vector auxiliar donde guardamos el recorrido.
		 * \param i posicion a examinar para el guardado.
		 * \param auxposicion Indica el lugar del vector auxiliar para guardar en el.
		 * \return TVectorPoro con el contenido del recorrido.
		 */
		TVectorPoro PostordenAux( TVectorPoro &, int , int & ) const;

        /** \brief TVectorPoro v
         *
         * Vector de poros que conforma la estructura interna del deap.
         */
		TVectorPoro v;

        /** \brief posicion
         *
         * Entero que indica la proxima posicion libre del vector "v".
         */
		int posicion;
};

#endif /* TDEAPPORO_H_ */
